#include "offline.h"
#include "RGB.h"
#include "rtthread.h"
#include "beep.h"


#define LOG_TAG              "offline"
#define LOG_LVL              LOG_LVL_DBG
#include <ulog.h>

offline_manage_obj offline_manage[OFFLINE_EVENT_MAX_NUM] = {NO_OFFLINE};


void offline_service_init(void)
{
    for (int i = 1; i < OFFLINE_EVENT_MAX_NUM; i++)
    {
        offline_manage[i].online_state = STATE_OFFLINE;
        offline_manage[i].last_time = rt_tick_get();
    }
    offline_manage[SYSTEM_PROTECT].enable = OFFLINE_ENABLE;
    offline_manage[SYSTEM_PROTECT].online_state = STATE_OFFLINE;

}

/**
  * @brief  check device offline.
  * @param
  * @retval void
  */
void offline_service(void *argument)
{
    offline_service_init();
    offline_event display_event;
    uint32_t time_now;

    while (1)
    {
        time_now = rt_tick_get();
        uint8_t beep_time = 0xFF;
        uint8_t error_level = 0XFF;
        display_event = NO_OFFLINE;

        for (int i = 1; i < OFFLINE_EVENT_MAX_NUM; i++)
        {
            uint32_t elapsed_ticks = time_now - offline_manage[i].last_time;
            uint32_t timeout_ticks = rt_tick_from_millisecond(offline_manage[i].offline_time);
            if ((elapsed_ticks > timeout_ticks) && (offline_manage[i].enable))
            {
                offline_manage[i].online_state = STATE_OFFLINE;
                if (error_level > offline_manage[i].error_level)
                {
                    error_level = offline_manage[i].error_level;
                }

                if (offline_manage[i].beep_times < beep_time)
                {
                    if (offline_manage[i].error_level <= OFFLINE_WARNING_LEVEL)
                    {
                        beep_time = offline_manage[i].beep_times;
                        display_event = (offline_event)i;
                        //LOG_E("offline_event:%d", display_event);
                    }
                }
            }
            else
            {
                offline_manage[i].online_state = STATE_ONLINE;
            }
        }

        if ((error_level == OFFLINE_ERROR_LEVEL) && (offline_manage[SYSTEM_PROTECT].enable))
        {
            offline_manage[SYSTEM_PROTECT].online_state = STATE_OFFLINE;
            //LOG_E("System offline\n");
        }
        else
        {
            offline_manage[SYSTEM_PROTECT].online_state = STATE_ONLINE;
        }

        if (display_event != NO_OFFLINE)
        {
            beep_set_times(offline_manage[display_event].beep_times);
            if (offline_manage[display_event].beep_times == 0)
            {
                aRGB_led_show(LED_Red);
            }
        }
        else
        {
            display_event = NO_OFFLINE;
            beep_set_times(0);
            aRGB_led_show(LED_Black);
        }
        rt_thread_mdelay(5);
    }
}


int offline_thread_entry_init(void)
{
    rt_err_t ret = RT_EOK;
    rt_thread_t thread = rt_thread_create("offline", offline_service, RT_NULL, 1024, 25, 10);
    /* 创建成功则启动线程 */
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
    }

    LOG_D("offline thread init success!\n");
    return ret;
}
INIT_APP_EXPORT(offline_thread_entry_init);



/**
  * @brief  get system offline event
  * @param
  * @retval void
  */
uint8_t get_system_status(void)
{
    return offline_manage[SYSTEM_PROTECT].online_state;
}

/**
  * @brief  register offline event
  * @param
  * @retval void
  */
void offline_event_init(offline_manage_obj obj)
{
    offline_event event = obj.event;

    offline_manage[event].event = event;
    offline_manage[event].enable = obj.enable;
    offline_manage[event].error_level = obj.error_level;


    offline_manage[event].beep_times = obj.beep_times;
    offline_manage[event].offline_time = obj.offline_time;

    offline_manage[event].last_time = rt_tick_get(); 
}



/**
  * @brief  update the information receive time.
  * @param
  * @retval void
  */
void offline_event_time_update(offline_event event)
{
    offline_manage[event].last_time = rt_tick_get();
}

/**
  * @brief  enable event offline check
  * @param
  * @retval void
  */
void offline_event_enable(offline_event event)
{
    offline_manage[event].enable = 1;
}

void offline_event_disable(offline_event event)
{
    offline_manage[event].enable = 0;
}
